package requests

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"net/http/httputil"
	Url "net/url"
	"strconv"
	"time"
)

// 发送一个get请求
func Get(url string, args ...interface{}) *requests {
	Rquest := requestInit{url: url, TimeOut: time.Second * 10}
	res, err := http.NewRequest("GET", Rquest.url, nil)
	if err != nil {
		fmt.Printf("Request requests creation failed. err:%v", err)
		return nil
	}
	// 处理传入的参数
	for _, value := range args {
		switch value := value.(type) {
		case Header:
			// 添加请求头
			Rquest.Header = value
		case Cookie:
			// 添加cookie
			Rquest.Cookie = value
		case Param:
			// 添加参数
			Rquest.Param = value
		case time.Duration:
			// 用于设置超时时间
			Rquest.TimeOut = value
		case Proxy:
			if err := setProxy(string(value), &Rquest); err != nil {
				fmt.Printf("%v", err)
				return nil
			}
		default:
			fmt.Printf("Passing in illegal format parameters.")
			return nil
		}
	}
	// 添加传入的参数
	if Rquest.Param != nil {
		data := Url.Values{}
		for k, v := range Rquest.Param {
			switch v := v.(type) {
			case string:
				data.Set(k, v)
			case int:
				data.Set(k, strconv.Itoa(v))
			default:
				fmt.Println("Incoming parameters are out of format")
				return nil
			}
		}
		u, err := Url.ParseRequestURI(url)
		if err != nil {
			fmt.Printf("parse url requestUrl failed. err:%v", err)
			return nil
		}
		u.RawQuery = data.Encode() // URL encode
		res.URL = u
	}
	// 处理Header
	if Rquest.Header != nil {
		for k, v := range Rquest.Header {
			res.Header.Add(k, v)
		}
	}
	// 处理Cookie
	if Rquest.Cookie != nil {
		for k, v := range Rquest.Cookie {
			sessionCookie := &http.Cookie{
				Name:  k,
				Value: v,
			}
			res.AddCookie(sessionCookie)
		}
	}
	// 发送请求
	client := &http.Client{
		Transport: func() http.RoundTripper {
			if Rquest.Proxy == nil {
				return nil
			} else {
				return Rquest.Proxy
			}
		}(),
		Timeout: Rquest.TimeOut,
	}
	// 读取该请求的请求包
	dump, err := httputil.DumpRequestOut(res, true)
	if err != nil {
		fmt.Printf("Failed to obtain HTTP packets. err:%v", err)
		return nil
	}
	// 发送请求
	respond, err := client.Do(res)
	if err != nil {
		fmt.Printf("connection failure!!! err:%v", err)
		return nil
	}
	defer respond.Body.Close()
	// 定义返回的结构体
	var resStruct requests
	// 逐步读取响应体数据并处理
	var buf bytes.Buffer
	_, err = io.Copy(&buf, respond.Body)
	if err != nil {
		fmt.Printf("Fail to read body. err:%v", err)
		return nil
	}
	// 在 buf 中可以获取到响应体数据
	resStruct.Text = buf.String()
	resStruct.HttpText = string(dump)
	resStruct.Status = respond.Status
	return &resStruct
}
